
exports.__esModule = true;
exports.default = void 0;

const _utils = require('../utils');

const _style = require('../utils/dom/style');

const _event = require('../utils/dom/event');

const _scroll = require('../utils/dom/scroll');

const _touch = require('../mixins/touch');

const _relation = require('../mixins/relation');

const _bindEvent = require('../mixins/bind-event');

// Utils
// Mixins
function genAlphabet() {
  const indexList = [];
  const charCodeOfA = 'A'.charCodeAt(0);

  for (let i = 0; i < 26; i++) {
    indexList.push(String.fromCharCode(charCodeOfA + i));
  }

  return indexList;
}

const _createNamespace = (0, _utils.createNamespace)('index-bar');
const createComponent = _createNamespace[0];
const bem = _createNamespace[1];

const _default = createComponent({
  mixins: [_touch.TouchMixin, (0, _relation.ParentMixin)('vanIndexBar'), (0, _bindEvent.BindEventMixin)(function (bind) {
    if (!this.scroller) {
      this.scroller = (0, _scroll.getScroller)(this.$el);
    }

    bind(this.scroller, 'scroll', this.onScroll);
  })],
  props: {
    zIndex: [Number, String],
    highlightColor: String,
    sticky: {
      type: Boolean,
      default: true,
    },
    stickyOffsetTop: {
      type: Number,
      default: 0,
    },
    indexList: {
      type: Array,
      default: genAlphabet,
    },
  },
  data: function data() {
    return {
      activeAnchorIndex: null,
    };
  },
  computed: {
    sidebarStyle: function sidebarStyle() {
      if ((0, _utils.isDef)(this.zIndex)) {
        return {
          zIndex: this.zIndex + 1,
        };
      }
    },
    highlightStyle: function highlightStyle() {
      const { highlightColor } = this;

      if (highlightColor) {
        return {
          color: highlightColor,
        };
      }
    },
  },
  watch: {
    indexList: function indexList() {
      this.$nextTick(this.onScroll);
    },
  },
  methods: {
    onScroll: function onScroll() {
      const _this = this;

      if ((0, _style.isHidden)(this.$el)) {
        return;
      }

      const scrollTop = (0, _scroll.getScrollTop)(this.scroller);
      const scrollerRect = this.getScrollerRect();
      const rects = this.children.map((item) => ({
        height: item.height,
        top: _this.getElementTop(item.$el, scrollerRect),
      }));
      const active = this.getActiveAnchorIndex(scrollTop, rects);
      this.activeAnchorIndex = this.indexList[active];

      if (this.sticky) {
        this.children.forEach((item, index) => {
          if (index === active || index === active - 1) {
            const rect = item.$el.getBoundingClientRect();
            item.left = rect.left;
            item.width = rect.width;
          } else {
            item.left = null;
            item.width = null;
          }

          if (index === active) {
            item.active = true;
            item.top = Math.max(_this.stickyOffsetTop, rects[index].top - scrollTop) + scrollerRect.top;
          } else if (index === active - 1) {
            const activeItemTop = rects[active].top - scrollTop;
            item.active = activeItemTop > 0;
            item.top = activeItemTop + scrollerRect.top - item.height;
          } else {
            item.active = false;
          }
        });
      }
    },
    getScrollerRect: function getScrollerRect() {
      if (this.scroller.getBoundingClientRect) {
        return this.scroller.getBoundingClientRect();
      }

      return {
        top: 0,
        left: 0,
      };
    },
    getElementTop: function getElementTop(ele, scrollerRect) {
      const { scroller } = this;

      if (scroller === window || scroller === document.body) {
        return (0, _scroll.getElementTop)(ele);
      }

      const eleRect = ele.getBoundingClientRect();
      return eleRect.top - scrollerRect.top + (0, _scroll.getScrollTop)(scroller);
    },
    getActiveAnchorIndex: function getActiveAnchorIndex(scrollTop, rects) {
      for (let i = this.children.length - 1; i >= 0; i--) {
        const prevHeight = i > 0 ? rects[i - 1].height : 0;
        const reachTop = this.sticky ? prevHeight + this.stickyOffsetTop : 0;

        if (scrollTop + reachTop >= rects[i].top) {
          return i;
        }
      }

      return -1;
    },
    onClick: function onClick(event) {
      this.scrollToElement(event.target);
    },
    onTouchMove: function onTouchMove(event) {
      this.touchMove(event);

      if (this.direction === 'vertical') {
        (0, _event.preventDefault)(event);
        const _event$touches$ = event.touches[0];
        const { clientX } = _event$touches$;
        const { clientY } = _event$touches$;
        const target = document.elementFromPoint(clientX, clientY);

        if (target) {
          const { index } = target.dataset;
          /* istanbul ignore else */

          if (this.touchActiveIndex !== index) {
            this.touchActiveIndex = index;
            this.scrollToElement(target);
          }
        }
      }
    },
    scrollToElement: function scrollToElement(element) {
      const { index } = element.dataset;

      if (!index) {
        return;
      }

      const match = this.children.filter((item) => String(item.index) === index);

      if (match[0]) {
        match[0].scrollIntoView();

        if (this.sticky && this.stickyOffsetTop) {
          (0, _scroll.setRootScrollTop)((0, _scroll.getRootScrollTop)() - this.stickyOffsetTop);
        }

        this.$emit('select', match[0].index);
      }
    },
    onTouchEnd: function onTouchEnd() {
      this.active = null;
    },
  },
  render: function render() {
    const _this2 = this;

    const h = arguments[0];
    const Indexes = this.indexList.map((index) => {
      const active = index === _this2.activeAnchorIndex;
      return h('span', {
        class: bem('index', {
          active,
        }),
        style: active ? _this2.highlightStyle : null,
        attrs: {
          'data-index': index,
        },
      }, [index]);
    });
    return h('div', {
      class: bem(),
    }, [h('div', {
      class: bem('sidebar'),
      style: this.sidebarStyle,
      on: {
        click: this.onClick,
        touchstart: this.touchStart,
        touchmove: this.onTouchMove,
        touchend: this.onTouchEnd,
        touchcancel: this.onTouchEnd,
      },
    }, [Indexes]), this.slots('default')]);
  },
});

exports.default = _default;
